package main

import (
	"fmt"
	"sort"
)

func main() {
	//通过 make 函数来创建切片，并指定底层数组的长度
	sli1 := make([]byte, 6, 10)                                          // 其中10为cap值，即底层数组长度，6为切片的初始长度
	fmt.Printf("sli1:%d, len:%d, cap:%d \n", sli1, len(sli1), cap(sli1)) //sli1:[0 0 0 0 0 0], len:6, cap:10
	sli2 := make([]byte, 6)                                              //如果没有在 make 中指定 cap 参数，那么底层数组长度 cap 就等于 len
	fmt.Printf("sli2:%d, len:%d, cap:%d \n", sli2, len(sli2), cap(sli2)) //sli2:[0 0 0 0 0 0], len:6, cap:6

	//直接使用make定义切片
	slice1 := make([]int, 4, 10)
	fmt.Println(slice1) //[0 0 0 0]
	for k, v := range slice1 {
		fmt.Printf("k=%d,v=%d \n", k, v)
	}

	//基于数组创建切片
	//采用 array[low : high : max]语法基于一个已存在的数组创建切片
	arrx := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	slx3 := arrx[3:7:9]
	fmt.Println(slx3) //[4 5 6 7]

	//数组和切片的关系变化
	var arr = [8]int{1, 2, 3, 4, 5, 6, 7, 8}
	var slice = arr[0:3]
	fmt.Println(slice, &arr[0] == &slice[0]) //[1 2 3] true

	//切片扩容
	slice[1] = 22             //把切片的第1位改成22: [1 22 3]
	slice = append(slice, 11) //给切片追加元素(也就是扩容)
	slice = append(slice, 12)
	slice = append(slice, 13)
	slice = append(slice, 14)
	fmt.Println(arr)                                                       //[1 22 3 11 12 13 14 8]
	fmt.Printf("slice=%d,len=%d,cap=%d \n", slice, len(slice), cap(slice)) //slice=[1 22 3 11 12 13 14],len=7,cap=8
	fmt.Println(&slice[0] == &arr[1])                                      //false, 此时原来的arr和现在的slice已经不是一个内存地址了

	//切片扩容
	var s []int
	s = append(s, 11)
	fmt.Println(s, len(s), cap(s)) //[11] 1 1
	s = append(s, 12)
	fmt.Println(s, len(s), cap(s)) //[11 12] 2 2
	s = append(s, 13)
	fmt.Println(s, len(s), cap(s)) //[11 12 13] 3 4
	s = append(s, 14)
	fmt.Println(s, len(s), cap(s)) //[11 12 13 14] 4 4
	s = append(s, 15)
	fmt.Println(s, len(s), cap(s)) //[11 12 13 14 15] 5 8

	//遍历切片
	for i := 0; i < len(slice); i++ {
		fmt.Print(slice[i], " ") //1 22 3 11 12 13 14
	}
	fmt.Println()

	for i, v := range slice {
		fmt.Printf("%d => %d\n", i, v)
	}
	/*
		0 => 1
		1 => 22
		2 => 3
		3 => 11
		4 => 12
		5 => 13
		6 => 14
	*/

	//切片的分割
	sli := []int{1, 2, 3, 4, 5, 6}
	fmt.Printf("len=%d cap=%d slice=%v\n", len(sli), cap(sli), sli) //len=6 cap=6 slice=[1 2 3 4 5 6]

	fmt.Println("sli[1] ==", sli[1])   //sli[1] == 2
	fmt.Println("sli[:] ==", sli[:])   //sli[:] == [1 2 3 4 5 6]
	fmt.Println("sli[1:] ==", sli[1:]) //sli[1:] == [2 3 4 5 6]
	fmt.Println("sli[:4] ==", sli[:4]) //sli[:4] == [1 2 3 4]

	fmt.Println("sli[0:3] ==", sli[0:3])                                           //sli[0:3] == [1 2 3]
	fmt.Printf("len=%d cap=%d slice=%v\n", len(sli[0:3]), cap(sli[0:3]), sli[0:3]) //len=3 cap=6 slice=[1 2 3]

	fmt.Println("sli[0:3:4] ==", sli[0:3:4])                                             //sli[0:3:4] == [1 2 3]
	fmt.Printf("len=%d cap=%d slice=%v\n", len(sli[0:3:4]), cap(sli[0:3:4]), sli[0:3:4]) //len=3 cap=4 slice=[1 2 3]

	//删除切片元素
	sli = []int{1, 2, 3, 4, 5, 6, 7, 8}
	fmt.Printf("len=%d cap=%d slice=%v\n", len(sli), cap(sli), sli) //len=8 cap=8 slice=[1 2 3 4 5 6 7 8]

	//删除尾部 2 个元素
	fmt.Printf("len=%d cap=%d slice=%v\n", len(sli[:len(sli)-2]), cap(sli[:len(sli)-2]), sli[:len(sli)-2]) //len=6 cap=8 slice=[1 2 3 4 5 6]

	//删除开头 2 个元素
	fmt.Printf("len=%d cap=%d slice=%v\n", len(sli[2:]), cap(sli[2:]), sli[2:]) //len=6 cap=6 slice=[3 4 5 6 7 8]

	//删除中间 2 个元素
	sli = append(sli[:3], sli[3+2:]...)
	fmt.Printf("len=%d cap=%d slice=%v\n", len(sli), cap(sli), sli) //len=6 cap=8 slice=[1 2 3 6 7 8]

	//切⽚之间共享存储结构
	year := []string{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
		"Oct", "Nov", "Dec"}
	Q2 := year[3:6]
	fmt.Println(Q2, len(Q2), cap(Q2)) //[Apr May Jun] 3 9
	summer := year[5:8]
	fmt.Println(summer, len(summer), cap(summer)) //[Jun Jul Aug] 3 7
	summer[0] = "Unknow"                          //这里修改子切片的值，原切片值也会被修改
	fmt.Println(Q2)                               //[Apr May Unknow]
	fmt.Println(year)                             //[Jan Feb Mar Apr May Unknow Jul Aug Sep Oct Nov Dec]

	//切片只能和nil比较，不能两个切片对比
	a := []int{1, 2, 3, 4}
	b := []int{1, 2, 3, 4}
	// fmt.Println(a == b) //切片只能和nil比较，所以此处会报错
	fmt.Println(a, b)

	//切片排序,可以使用冒泡
	sl := []int{15, 23, 8, 10, 7}
	for i := 1; i < len(sl); i++ {
		for j := 0; j < len(sl)-i; j++ {
			if sl[j] > sl[j+1] {
				sl[j], sl[j+1] = sl[j+1], sl[j]
			}
		}
	}
	fmt.Println(sl) //[7 8 10 15 23]

	//也可以直接使用sort包下的排序方法
	sl2 := []int{19, 2, 8, 11, 30}
	sort.Ints(sl2)
	fmt.Println(sl2) //[2 8 11 19 30]

	//字符串切片排序
	sl3 := []string{"Apple", "Windows", "Orange", "abc", "你好", "acd", "acc"}
	sort.Strings(sl3)
	fmt.Println(sl3) //[Apple Orange Windows abc acc acd 你好]
}
